#include <iostream>
#include <memory>
#include <common.h>
#include <thread>
#include <chrono>
using namespace std;


namespace CIRCULAR_DAY17
{
    class B;
    struct A{
        shared_ptr<B> b;
    };
    struct B{
        shared_ptr<A> a;
    };
};

namespace CIRCULAR_GO_DAY17
{
    class B;
    struct A{
        weak_ptr<B> b;
    };
    struct B{
        weak_ptr<A> a;
    };
};

namespace THREAD_DAY17
{
    struct Foo
    {
        Foo(int i):i_(i){}
        void print() {std::cout << i_ << std::endl;}
        int i_;
    };
};

namespace CIRCULAR_ALL_DAY17
{
    class B;

    class A
    {
        private:
            int x_;
        public:
            A()
            {
                cout << "A构造函数" << endl;
            }

            virtual ~A()
            {
                cout << "A析构函数" << endl;
            }
            std::shared_ptr<B> ptrB;

    };

    class B
    {
        private:
            int x_;
        public:
            B()
            {
                cout << "B构造函数" << endl;
            }
            virtual ~B()
            {
                cout << "B析构函数" << endl;
            }
            std::shared_ptr<A> ptrA;
    };
};



int main(int argc, char *argv[])
{
    {
        __LOG__("shared_ptr循环引用");
        using namespace CIRCULAR_DAY17;
        auto pa = make_shared<A>();
        auto pb = make_shared<B>();
        pa->b = pb;
        pb->a = pa;

        cout << "pa引用个数: " << pa.use_count() << " pb引用个数: " << pb.use_count() << endl;
    }

    {
        __LOG__("weak_ptr解决循环引用");
        using namespace CIRCULAR_GO_DAY17;
        auto pa = make_shared<A>();
        auto pb = make_shared<B>();
        pa->b = pb;
        pb->a = pa;

        cout << "pa引用个数: " << pa.use_count() << " pb引用个数: " << pb.use_count() << endl;
    }

    {
        __LOG__("shared_ptr线程不安全");
        using namespace THREAD_DAY17;
        {
            auto shptr = std::make_shared<Foo>(42);
            // 传引用会引起报错，直接传对象
            std::thread([shptr](){
                std::this_thread::sleep_for(std::chrono::seconds(1));
                shptr->print();
            }).detach();
        }
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }

    {
        __LOG__("循环引用的解决");
        using namespace CIRCULAR_ALL_DAY17;
        auto pa = make_shared<A>();
        auto pb = make_shared<B>();

        cout << "pa引用个数: " << pa.use_count() << " pb引用个数: " << pb.use_count() << endl;
        pa->ptrB = pb;
        pb->ptrA = pa;
        cout << "pa引用个数: " << pa.use_count() << " pb引用个数: " << pb.use_count() << endl;
 
    }

    
    return 0;
}


